﻿
// Calculator.cpp: 定义应用程序的类行为。
//

#include "pch.h"
#include "framework.h"
#include "Calculator.h"
#include "CalculatorDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CCalculatorApp

BEGIN_MESSAGE_MAP(CCalculatorApp, CWinApp)
	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CCalculatorApp 构造

CCalculatorApp::CCalculatorApp()
{
	// 支持重新启动管理器
	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;

	// TODO: 在此处添加构造代码，
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的 CCalculatorApp 对象

CCalculatorApp theApp;


// CCalculatorApp 初始化

BOOL CCalculatorApp::InitInstance()
{
	// 如果一个运行在 Windows XP 上的应用程序清单指定要
	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式，
	//则需要 InitCommonControlsEx()。  否则，将无法创建窗口。
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	// 将它设置为包括所有要在应用程序中使用的
	// 公共控件类。
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinApp::InitInstance();


	AfxEnableControlContainer();

	// 创建 shell 管理器，以防对话框包含
	// 任何 shell 树视图控件或 shell 列表视图控件。
	CShellManager *pShellManager = new CShellManager;

	// 激活“Windows Native”视觉管理器，以便在 MFC 控件中启用主题
	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小，则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串，
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	CCalculatorDlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  “确定”来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  “取消”来关闭对话框的代码
	}
	else if (nResponse == -1)
	{
		TRACE(traceAppMsg, 0, "警告: 对话框创建失败，应用程序将意外终止。\n");
		TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件，则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
	}

	// 删除上面创建的 shell 管理器。
	if (pShellManager != nullptr)
	{
		delete pShellManager;
	}

#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS)
	ControlBarCleanUp();
#endif

	// 由于对话框已关闭，所以将返回 FALSE 以便退出应用程序，
	//  而不是启动应用程序的消息泵。
	return FALSE;


}

//新建数据栈
void initStack(SqStack * &s) {
     s = new SqStack();
     s->top = -1;

}
//将字符入栈
bool Push(SqStack * &s, char e) {
     if (s->top == maxsize - 1)
         return false;
     s->top++;
     s->data[s->top] = e;
     return true;

}
//字符出栈
bool Pop(SqStack * &s, char& e) {
     if (s->top == -1)
         return false;
     e = s->data[s->top];
     s->top--;
     return true;

}
//获取栈顶元素
bool GetTop(SqStack * s, char& e) {
     if (s->top == -1)
         return false;
     e = s->data[s->top];
     return true;

}
//释放栈内存
void DestroyStack(SqStack * &s) {
     free(s);

}
//判断栈空
bool StackEmpty(SqStack * s) {
     return (s->top == -1);

}

//新建数据栈
void initStack(SqStackN * &s) {
     s = new SqStackN();
     s->top = -1;

}
//将数据入栈
bool Push(SqStackN * &s, double e)
{
     if (s->top == maxsizen - 1)
         return false;
     s->top++;
     s->data[s->top] = e;
     return true;
}
//数据出栈
bool Pop(SqStackN * &s, double& e)
{
     if (s->top == -1)
         return false;
     e = s->data[s->top];
     s->top--;
     return true;
}
//获得栈顶元素
bool GetTop(SqStackN * s, double& e)
{
     if (s->top == -1)
         return false;
     e = s->data[s->top];
     return true;
}
//释放栈内存
void DestroyStack(SqStackN * &s) {
     free(s);
}
//判断栈空
bool StackEmpty(SqStackN * s)
{
     return (s->top == -1);
}



//检查输入错误
int wrong(char* WExp) {
    int k1 = 0,i;
    double d=0.0, z, x = 0.0;
    while (*WExp !='\0') {
        switch (*WExp)
        {
        case'/':
            WExp++;
            while (*WExp == '.' || *WExp == '(' || *WExp >= '0' && *WExp <= '9') {//到达下一个运算符之前
                if (*WExp == '.') {
                    WExp++;
                    x += 1;
                    while (*WExp >= '0' && *WExp <= '9') {//将除数转化为一个double型数字
                        x *= 10;
                        double n = *WExp-48;
                        z = n / x;
                        d = d + z;
                        WExp++;
                    }
                    break;
                }
                else if (*WExp == '(') {        //若除法后面为括号运算符
                    k1 += 1;
                    WExp++;
                }
                else {
                    i= *WExp-48;
                    d = d * 10 + i;
                    WExp++;
                }
            }
            if (*WExp == '/') {
                AfxMessageBox(_T("很抱歉\n您不能连续输入两个运算符。"));
                return 9;
            }
            if (d == 0.0) {
                AfxMessageBox(_T("很抱歉\n除数不能为零。"));
                return 9;
            }
            continue;
        case'+':
        case'-':
        case'*':
        
            WExp++;
            if (*WExp == '+' || *WExp == '-' || *WExp == '*' || *WExp == '/') {
                AfxMessageBox(_T("很抱歉\n您不能连续输入两个运算符。"));
                return 9;
            }
            else {
                continue;
            }
        case'(':
            k1 += 1;
            break;
        case')':
            k1 -= 1;
            break;
        case'.':
            WExp++;
            while (*WExp>='0'&&*WExp<='9'||*WExp=='.') {//到达下一个运算符之前
                if (*WExp == '.') {//再次检测到小数点
                    AfxMessageBox(_T("很抱歉\n您的某个数据输入了两个或两个以上的小数点,请重新检查后再次输入。"));
                    return 9;
                }
                WExp++;
            }
            continue;
        default:
            if (*WExp >= '0' && *WExp <= '9')
                break;
            else {
                AfxMessageBox(_T("很抱歉\n您输入了不合法的字符，请重新检查！"));
                return 9;
            }
        }
        WExp++;
    }
    if (k1 != 0) {
        AfxMessageBox(_T("很抱歉\n您输入的括号不对称！"));
        return 9;
    }
}

//将中缀表达式转化为后缀表达式
void change(char* exp, char postexp[]) {
    char e;
    SqStack * s;    initStack(s);
    int p = 0;
    while (*exp != '\0') {
         switch (*exp){
            case '+':
            case '-':
                 while (!StackEmpty(s)) {
                     GetTop(s, e);
                     if (e != '(') {
                         postexp[p++] = e;
                         Pop(s, e);
                     }
                     else
                         break;
			     }
                 Push(s, *exp);
                 exp++; break;
            case '*':
            case '/':
                 while (!StackEmpty(s)) {
                     GetTop(s, e);
                    if (e == '*' || e == '/') {
                        postexp[p++] = e;
                        Pop(s, e);
				    }
                     else
                       break;
			     }
                Push(s, *exp);
                exp++; break;
            case '(':
                 Push(s, *exp);
                 exp++; 
                 break;
            case ')':
                 Pop(s, e);
                 while (e != '(') {
                     postexp[p++] = e;
                     Pop(s, e); 
			     }
                 exp++;
                 break;
            default:
                while (*exp >= '0' && *exp <= '9' || *exp == '.') {
                    postexp[p++] = *exp;
                    exp++;
                }
                postexp[p++] = '#'; break;
         }
	}
     while (!StackEmpty(s)) {
         Pop(s, e);
         postexp[p++] = e;
	 }
     postexp[p] = '\0';
     DestroyStack(s);
}
//计算操作
double calculate(char* postexp) {
     double a, b, c, d, e;
     int x = 0;
     SqStackN * Number;    initStack(Number);
     while (*postexp != '\0') {
         switch (*postexp)
         {
          case '+':
             Pop(Number, a);
             Pop(Number, b);
             c = b + a;
             Push(Number, c);
             break;
         case '-':
             Pop(Number, a);
             Pop(Number, b);
             c = b - a;
             Push(Number, c);
             break;
         case '*':
             Pop(Number, a);
             Pop(Number, b);
             c = b * a;
             Push(Number, c);
             break;
         case '/':
             Pop(Number, a);
             Pop(Number, b);
             c = b / a;
             Push(Number, c);
             break;
         default:
            d = 0;
            //将小数同样存入数据中
            while (*postexp == '.' || *postexp >= '0' && *postexp <= '9') {
                if (*postexp == '.') {//小数点后小于零
                    postexp++;
                    x += 1;
                    while (*postexp >= '0' && *postexp <= '9') {
                        x *= 10;
                        double n = *postexp - 48;
                        d = d + n / x;//将小数点后的数据依次除以10并加入到变量‘d’中。
                        postexp++;
                    }
                    break;
                }
                else {
                    d = d * 10 + (*postexp - 48);
                    postexp++;
                }
            }
            Push(Number, d);
            break;  
         }
         x = 0;
         postexp++;
     }
     GetTop(Number, e);
     DestroyStack(Number);
     return e;
}
